package com.bw.bwskinfilecreator;


import com.bw.bwskinfilecreator.bean.ProjectConfigEntity;
import com.bw.bwskinfilecreator.bean.UtilConfigEntity;
import com.bw.bwskinfilecreator.utils.FileUtils;
import com.google.gson.Gson;
import org.eclipse.jgit.api.Git;

import java.io.*;
import java.util.ArrayList;
import java.util.Objects;

public class XxSKinUtil {
    public static final int TYPE_OPEN_EXPLORE = 2;
    public static final int TYPE_PUSH_TO_DEVICE = TYPE_OPEN_EXPLORE << 1;
    public static final int TYPE_REPLACE_TO_GIT = TYPE_OPEN_EXPLORE << 2;
    private static UtilConfigEntity utilConfigEntity;
    private UtilConfigProvider utilConfigProvider;
    private String packageName;

    public XxSKinUtil(UtilConfigProvider utilConfigProvider) {
        this.utilConfigProvider = utilConfigProvider;
        saveConfig();
    }

    /**
     * 获取项目缓存所在目录
     *
     * @return
     */
    public static String getUtilCachePath() {
        return new File(XxSKinUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile().getParentFile().getAbsolutePath() + "\\util_cache";
    }

    /**
     * 获取项目缓存所在目录
     *
     * @return
     */
    public static String getProjectCachePath() {
        return new File(XxSKinUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile().getParentFile().getAbsolutePath() + "\\project_cache";
    }


    private void saveConfig() {

        UtilConfigEntity utilConfig = getUtilConfig();
        //保存数据到本地
        File file = new File(getUtilCachePath());
        FileUtils.createFileByDeleteOldFile(file);
        try {
            PrintWriter printWriter = new PrintWriter(file);
            printWriter.print(new Gson().toJson(utilConfig));
            printWriter.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        // 在主类（继承自Application的类）或控制器中使用

    }

    public void launch() {
        //准备工作
        try {
            boolean result = onBeforeMakeSkin();
            if (!result) return;
            //打包
            makeSkin();
            //处理打包资源
            onAfterMakeSkin();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取工具配置
     *
     * @return
     */
    private UtilConfigEntity getUtilConfig() {
        if (utilConfigEntity == null) {
            utilConfigEntity = new UtilConfigEntity();
        }
        utilConfigEntity.setProjectConfigEntity(getUtilConfigProvider().getProject());
        utilConfigEntity.setSkinProjectPath(getUtilConfigProvider().getSkinProjectPath());
        //功能选项
        utilConfigEntity.setNeedOpenExplore((getUtilConfigProvider().launchType() & TYPE_OPEN_EXPLORE) != 0);
        utilConfigEntity.setNeedPushToDevice((getUtilConfigProvider().launchType() & TYPE_PUSH_TO_DEVICE) != 0);
        utilConfigEntity.setNeedPushToGit((getUtilConfigProvider().launchType() & TYPE_REPLACE_TO_GIT) != 0);
        return utilConfigEntity;
    }

    /**
     * 制作皮肤包
     */
    private boolean makeSkin() {
        try {
            getUtilConfigProvider().onLog("------开始制作基础皮肤包------");
            String command = getUtilConfig().getSkinProjectPath() + "\\assembleRelease.cmd"; // 要执行的命令
            Process process = Runtime.getRuntime().exec(command); // 执行命令
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); // 获取命令输出流
            String line;
            ArrayList<String> content = new ArrayList<>();
            while ((line = reader.readLine()) != null) { // 逐行读取输出结果
                content.add(line);
                getUtilConfigProvider().onLog(line);
            }
            reader.close();
            int exitCode = process.waitFor(); // 等待命令执行完成并获取退出码
            if (exitCode == 1) return false;
            getUtilConfigProvider().onLog("------制作基础皮肤包" + (exitCode == 0 ? "完成" : "失败") + "------");
            return true;

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return false;
    }

    /**
     * 制作皮肤包之前的准备工作
     */
    private boolean onBeforeMakeSkin() throws IOException {
        getUtilConfigProvider().onLog("------资源准备阶段开始------");
        String originResPath = getUtilConfigProvider().getProject().getSourceProjectPath() + "\\src";
        String skinResPath = getUtilConfig().getSkinProjectPath() + "\\app\\src";
        //先清空模板工程
        boolean delResult = FileUtils.deleteAllInDir(skinResPath);
        getUtilConfigProvider().onLog("    清空模板工程资源 " + (delResult ? "完成" : "失败"));
        if (!delResult) return false;
        //清除皮肤包
        boolean delSkinResult = FileUtils.deleteAllInDir(getUtilConfig().getSkinProjectPath() + "\\app\\build");
        getUtilConfigProvider().onLog("    清空皮肤包 " + (delSkinResult ? "完成" : "失败"));
        if (!delSkinResult) return false;
        //复制皮肤资源到打包工程
        boolean copyResult = FileUtils.copy(originResPath, skinResPath);
        getUtilConfigProvider().onLog("    复制资源到模板工程 " + (copyResult ? "完成" : "失败"));
        if (!copyResult) return false;
        getUtilConfigProvider().onLog("------资源准备阶段结束------");
        //获取应用包名
        loadPackageName();
        boolean cmdResult = createCmd();
        getUtilConfigProvider().onLog("    编译命令准备" + (cmdResult ? "完成" : "失败"));
        return cmdResult;
    }

    private void loadPackageName() {
        File file = new File(getUtilConfig().getSkinProjectPath() + "\\app\\src\\main\\AndroidManifest.xml");
        BufferedReader bufferedReader;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                //截取包名
                if (line.contains("package=\"")) {
                    packageName = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                    getUtilConfigProvider().onLog(" " + packageName);
                    break;
                }
            }
            bufferedReader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成皮肤工程的打包命令
     *
     * @return
     */
    private boolean createCmd() {
        //在皮肤工程下创建 assembleRelease.cmd 文件
        boolean cmdFileCreateSuccess = FileUtils.createFileByDeleteOldFile(getUtilConfig().getSkinProjectPath() + "\\assembleRelease.cmd");
        if (!cmdFileCreateSuccess) return false;
        //写入内容 cd
        File file = new File(getUtilConfig().getSkinProjectPath() + "\\assembleRelease.cmd");
        try {
            PrintWriter printWriter = new PrintWriter(file);
            printWriter.append("cd ").append(getUtilConfig().getSkinProjectPath()).append("\n").append("./gradlew assembleRelease").flush();
            printWriter.close();
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    /**
     * 皮肤包制作完成之后的收尾工作
     */
    private void onAfterMakeSkin() throws IOException {
        String outFileDir = getUtilConfig().getSkinProjectPath() + "\\app\\build\\outputs\\apk\\release\\";
        //找到目录下第一个文件
        File dir = new File(outFileDir);
        File file = Objects.requireNonNull(dir.listFiles())[0];
        //修改名称
        String skinFileName = getUtilConfig().getProjectConfigEntity().getSkinFileName();
        //重命名
        FileUtils.rename(file, skinFileName);
        getUtilConfigProvider().onLog("    修改皮肤包名称为 " + skinFileName);


        if (getUtilConfig().isNeedOpenExplore()) {
            getUtilConfigProvider().onLog("    打开目录 " + outFileDir);
            //打开对应的输出目录
            Runtime.getRuntime().exec("explorer " + outFileDir);
        }


        if (getUtilConfig().isNeedPushToGit()) {
            //还原修改
            //更新本地git目录
//            Runtime.getRuntime().exec("git -C" + configProvider.getSkinGitPath() + "\\" + configProvider.getProjectPackageName() + " pull");
            //切换分支
            //执行git add .
            //执行git cz
            // 输入内容
            //提交
            //打开git目录
//            Runtime.getRuntime().exec("explorer " + "D:\\BWProject\\bw_skin\\skin_bags\\daytime_mode\\"+configProvider.getProjectPackageName());

            String gitPath = getUtilConfig().getProjectConfigEntity().getGitProjectPath() + "\\" + packageName;
            getUtilConfigProvider().onLog("    打开目录 " + gitPath);
            Runtime.getRuntime().exec("explorer " + gitPath);

            //替换皮肤包到对应包名目录下
            //复制并替换到仓库目录
            boolean copy = FileUtils.copy(outFileDir + "/" + skinFileName, gitPath + "/" + skinFileName);
            getUtilConfigProvider().onLog("    替换到仓库目录" + (copy ? "完成" : "失败"));
            //执行上传命令
        }


        if (getUtilConfig().isNeedPushToDevice()) {
            //推送到设备
            getUtilConfigProvider().onLog("    推送皮肤包到设备...");
            Runtime.getRuntime().exec("adb root");
            Runtime.getRuntime().exec("adb remount");
            getUtilConfigProvider().onLog("    adb push " + outFileDir + skinFileName + " /system/media/bwskin/" + getUtilConfig().getProjectConfigEntity().getDeviceSkinFolderName() + "/" + packageName + "/" + skinFileName);
            Process exec = Runtime.getRuntime().exec("adb push " + outFileDir + skinFileName + " /system/media/bwskin/" + getUtilConfig().getProjectConfigEntity().getDeviceSkinFolderName() + "/" + packageName + "/" + skinFileName);

            try {
                int resultCode = exec.waitFor();
                if (resultCode != 0) {
                    getUtilConfigProvider().onLog("    推送皮肤包到设备失败");
                    return;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            getUtilConfigProvider().onLog("    推送皮肤包到设备");

            //重启应用
            Runtime.getRuntime().exec("adb shell sync");
            Runtime.getRuntime().exec("adb shell pkill " + packageName);
            getUtilConfigProvider().onLog("    重启应用 " + packageName);
        }


    }


    private UtilConfigProvider getUtilConfigProvider() {
        return utilConfigProvider;
    }

    public void setUtilConfigProvider(UtilConfigProvider utilConfigProvider) {
        this.utilConfigProvider = utilConfigProvider;
    }


    public interface UtilConfigProvider {
        /**
         * 获取皮肤工程所在路径
         *
         * @return
         */
        String getSkinProjectPath();

        /**
         * 选择的项目名称
         */
        ProjectConfigEntity getProject();

        /**
         * 启动类型
         * 0:完成后打开所在目录
         * 1:完成后推送到设备
         * 2:完成后替换到Git上传路径
         */
        int launchType();


        void onLog(String msg);
    }

}
